package cn.script.game.opt;

import cn.script.call_api.AfterApi;
import cn.script.call_api.MoveOpt;
import cn.script.call_api.OptApi;
import cn.script.domain.Point;
import cn.script.domain.RangePoint;
import cn.script.domain.Skill;
import cn.script.exception.StopException;
import cn.script.game.GameInfo;
import cn.script.util.Delay;
import cn.script.util.LogOut;

/**
 * 移动到指定的位置
 *
 * @author 周永波
 */
public class MoveLocation implements OptApi {

    private String cityName;

    private Point winPoint;

    private Point gamePoint;

    private AfterApi afterApi;

    private GameInfo gi;

    private int rx = 0;

    private int ry = 0;

    private Point nowPoint;
    /**
     * 当前连续坐标重复的次数
     */
    private int num = 0;

    /**
     * 当移动卡死时操作
     */
    private MoveOpt moveOpt = () -> {
        Skill skill = new Skill("f4", 0, 50);
        RangePoint range = new RangePoint(314, 133, 481, 329);
        for (int i = 0; i < 2; i++) {
            this.gi.wio().moveToEx(range, 100);
            this.gi.wio().keypress(skill.key(), 200);
            Delay.delay(3000);
        }
        return 1;
    };

    public MoveLocation(GameInfo gi, String cityName) {
        this.gi = gi;
        this.cityName = cityName;
    }

    public MoveLocation winPoint(Point point) {
        this.winPoint = point;
        return this;
    }

    public MoveLocation gamePoint(Point point) {
        this.gamePoint = point;
        return this;
    }

    public MoveLocation winPoint(int x, int y) {
        this.winPoint = Point.point(x, y);
        return this;
    }

    public MoveLocation gamePoint(int x, int y) {
        this.gamePoint = Point.point(x, y);
        return this;
    }

    public MoveLocation rPoint(int rx, int ry) {
        this.rx = rx;
        this.ry = ry;
        return this;
    }

    public MoveLocation num(int num) {
        this.num = num;
        return this;
    }

    public MoveLocation moveOpt(MoveOpt moveOpt) {
        this.moveOpt = moveOpt;
        return this;
    }

    public MoveLocation after(AfterApi afterApi) {
        this.afterApi = afterApi;
        return this;
    }

    public int optx() {
        if (this.winPoint == null || this.gamePoint == null) {
            return 1;
        }
        if (!this.gi.isCity(this.cityName)) {
            LogOut.out("当前移动位置不对;目标位置:%s=>当前位置:%s", this.cityName, this.gi.nowCity());
            throw new StopException();
        }
        LogOut.out("开始像目的地出发:%s=>%d,%d", this.cityName, this.gamePoint.x(), this.gamePoint.y());
        int i = 0;
        Long startTime = System.currentTimeMillis();
        while (true) {
            if (System.currentTimeMillis() - startTime > 20000) {
                LogOut.out("移动到目标地点超时");
                throw new StopException();
            }
            Point nowPoint = this.gi.nowCd();
            if (nowPoint == null) {
                LogOut.out("无法获取当前位置信息");
                throw new StopException();
            }
            if (this.gamePoint.isRg(nowPoint, this.rx, this.ry)) {
                LogOut.out("已移动到目的地:%d,%d", nowPoint.x(), nowPoint.y());
                return 1;
            }
            // 阻塞移动判断
            if (this.nowPoint != null && this.nowPoint.isRg(nowPoint, 3, 3)) {
                this.num += 1;
            } else {
                this.num = 0;
            }
            this.nowPoint = nowPoint;
            Point clickPoint = this.winPoint;
            if (this.num == 2) {
                clickPoint = Point.point(this.winPoint.x() + 2, this.winPoint.y() + 2);
            } else if (this.num > 4) {
                if (this.moveOpt != null) {
                    if (this.moveOpt.opt() == 0) {
                        LogOut.out("移动阻塞;阻塞操作失败");
                        return 1;
                    }
                    Delay.delay(5000);
                    this.clickMap(Point.point(400, 300));
                    Delay.delay(3000);
                    LogOut.out("移动阻塞;阻塞操作成功");
                    this.num = 0;
                    continue;
                }
                throw new StopException();
            }

            this.clickMap(clickPoint);
            i++;
            Delay.delay(500);
        }
    }

    @Override
    public int opt() {
        int optx = this.optx();
        if (optx == 1 && this.afterApi != null) {
            this.afterApi.opt();
        }
        return optx;
    }

    private void clickMap(Point pi) {
        this.gi.openMap();
        this.gi.wio().leftClick(pi, 100);
        this.gi.wio().keypress("esc");
    }
}
